﻿using YNTK;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Text;
using System.Reflection;

namespace SqlSugar
{
    /// <summary>
    /// 非泛型 SqlSugar 仓储
    /// </summary>
    public partial class SqlSugarRepository : ISqlSugarRepository
    {
        /// <summary>
        /// 服务提供器
        /// </summary>
        private readonly IServiceProvider _serviceProvider;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serviceProvider">服务提供器</param>
        public SqlSugarRepository(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual ISqlSugarRepository<TEntity> Change<TEntity>()
            where TEntity : class, new()
        {
            return _serviceProvider.GetService<ISqlSugarRepository<TEntity>>();
        }
    }

    /// <summary>
    /// SqlSugar 仓储实现类
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public partial class SqlSugarRepository<TEntity> : ISqlSugarRepository<TEntity>
    where TEntity : class, new()
    {
        /// <summary>
        /// 非泛型 SqlSugar 仓储
        /// </summary>
        private readonly ISqlSugarRepository _sqlSugarRepository;

        /// <summary>
        /// 初始化 SqlSugar 客户端
        /// </summary>
        private readonly SqlSugarScope _db;

        /// <summary>
        /// 初始化 ITenant 客户端
        /// </summary>
        private readonly ITenant _tenant;

        /// <summary>
        /// 租户ID或者数据库连接ID
        /// </summary>
        private readonly string tenantId;

        /// <summary>
        /// 数据库名称
        /// </summary>
        private readonly string tenantDbName;

        /// <summary>
        /// 数据库类型
        /// </summary>
        private readonly DbType dbType;

        /// <summary>
        /// 数据库类型
        /// </summary>
        private readonly IocDbType iocDbType;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugarRepository"></param>
        /// <param name="db"></param>
        public SqlSugarRepository(ISqlSugarRepository sqlSugarRepository, ISqlSugarClient db)
        {
            _sqlSugarRepository = sqlSugarRepository;

            DynamicContext = Context = _db = (SqlSugarScope)db;
            Ado = _db.Ado;

            tenantId = App.Configuration["ConnectionStrings:ConfigId"];
            tenantDbName = App.Configuration["ConnectionStrings:DBName"];
            dbType = (DbType)Enum.Parse(typeof(DbType), App.Configuration["ConnectionStrings:DBType"]);
            iocDbType = (IocDbType)Enum.Parse(typeof(IocDbType), App.Configuration["ConnectionStrings:DBType"]);

            _tenant = _db;
            var httpContext = App.HttpContext;
            if (httpContext != null && httpContext.User.FindFirst("TenantId")?.Value != null)
            {
                tenantId = httpContext.User.FindFirst("TenantId")?.Value;
                tenantDbName = httpContext.User.FindFirst("TenantDbName")?.Value;
                _tenant.AddConnection(new ConnectionConfig()
                {
                    DbType = dbType,
                    ConfigId = tenantId,//设置库的唯一标识
                    IsAutoCloseConnection = true,
                    ConnectionString = string.Format($"{App.Configuration["ConnectionStrings:DefaultConnection"]}", tenantDbName)
                });
                SugarIocServices.AddSqlSugar(new IocConfig()
                {
                    ConnectionString = string.Format($"{App.Configuration["ConnectionStrings:DefaultConnection"]}", tenantDbName),
                    DbType = iocDbType,
                    ConfigId = tenantId,
                    IsAutoCloseConnection = true//自动释放
                });
                //DbScoped.SugarScope.ChangeDatabase(tenantId);
            }
            else
            {
                tenantId = App.Configuration["ConnectionStrings:ConfigId"];
            }
            _tenant.ChangeDatabase(tenantId);

            //调式代码 用来打印SQL 
            _db.Aop.OnLogExecuting = (sql, pars) =>
            {
                Console.WriteLine(sql + "\r\n" + _db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));             
            };
        }

        /// <summary>
        /// 实体集合
        /// </summary>
        public virtual ISugarQueryable<TEntity> Entities => _db.Queryable<TEntity>();

        /// <summary>
        /// 数据库上下文
        /// </summary>
        public virtual SqlSugarScope Context { get; }

        /// <summary>
        /// 动态数据库上下文
        /// </summary>
        public virtual dynamic DynamicContext { get; }

        /// <summary>
        /// 原生 Ado 对象
        /// </summary>
        public virtual IAdo Ado { get; }

        #region sql操作
        /// <summary>
        /// 执行给定的命令
        /// </summary>
        /// <param name="sql">命令字符串</param>
        /// <param name="parameters">要应用于命令字符串的参数</param>
        /// <returns>执行命令后由数据库返回的结果</returns>
        public async Task<int> ExecuteAsync(string sql, params object[] parameters)
        {
            return await _db.Ado.ExecuteCommandAsync(sql, parameters);
        }

        /// <summary>
        /// SqlServer带Go的脚本处理
        /// </summary>
        /// <param name="sql">sql</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public int ExecuteCommandWithGo(string sql, params SugarParameter[] parameters)
        {
            //go语句是独立一行就支持
            return _db.Ado.ExecuteCommandWithGo(sql, parameters);
        }

        /// <summary>
        /// 原生SQL获取数据
        /// </summary>
        /// <param name="sql">sql</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public async Task<List<TEntity>> SqlQueryAsync(string sql, params object[] parameters)
        {
            return await _db.Ado.SqlQueryAsync<TEntity>(sql, parameters);
        }

        /// <summary>
        /// 原生SQL查询2个结果集
        /// </summary>
        /// <param name="sql">sql</param>
        /// <param name="parameters">参数</param>
        /// <returns></returns>
        public async Task<Tuple<List<T1>,List<T2>>> SqlQueryAsync<T1, T2>(string sql, params object[] parameters)
        {
            return await _db.Ado.SqlQueryAsync<T1, T2>(sql, parameters);
        }

        /// <summary>
        /// 使用原生sql分页查询
        /// 在查询条件的DTO中给字段加特性ConditionsAttribute
        /// 没有ConditionsAttribute特性时，会根据字段自身的类型进行查询，int时按=，string时按like，datetime时搜索当天
        /// 有特性时 跟根据特性一定的特性来进行搜索
        /// NotSelect为永不查询，即使DTO中有值也不会查询
        /// Enable是否启用，如果不启用的话，同没有特性的逻辑（已废弃）
        /// symbolAttribute是判断字符运算符，根据运算符进行查询，目前有=，>,<,>=,<=,like，范围等，详情请看SymbolAttribute枚举
        /// IsSplit为是否有分隔符，只有在运算符为范围时生效
        /// SplitString是分隔符的字符，只有在IsSplit为true时生效
        /// 另外，此方法还支持自定义写查询条件，可以在param中定义不在DTO中的查询条件，写在sql字符串中即可
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="D"></typeparam>
        /// <param name="sql"></param>
        /// <param name="queryParameter"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> SqlQueryAndParameterAsync<T, D>(string sql, 
            QueryParameter<D> queryParameter,List<SqlParameter> param = null) where T : class, new() where D : class, new()
        {
            StringBuilder strsql = new StringBuilder();
            strsql.Append(@"select * from (" + sql + ") t where 1=1");
            if (param == null)
            {
                param = new List<SqlParameter>();
            }
            var datadto = queryParameter.data;
            if (datadto != null)
            {
                PropertyInfo[] propertys = datadto.GetType().GetProperties();
                foreach (var item in propertys)
                {
                    var attribute = item.GetCustomAttribute<ConditionsAttribute>();
                    var type = item.PropertyType.FullName;
                    var value = item?.GetValue(datadto);
                    var valueS = Convert.ToString(item?.GetValue(datadto));
                    if (string.IsNullOrWhiteSpace(valueS))
                    {
                        continue;
                    }
                    if (attribute == null)
                    {
                        if (type.Contains("Int"))
                        {
                            if (Convert.ToInt32(value) <= 0)
                            {
                                continue;
                            }
                            param.Add(new SqlParameter("@" + item.Name, value));
                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                        }
                        else if (type.Contains("String"))
                        {
                            param.Add(new SqlParameter("@" + item.Name, "%" + value + "%"));
                            strsql.Append(" and t." + item.Name + " like @" + item.Name);
                        }
                        else if (type.Contains("Datetime"))
                        {
                            var date = ((DateTime)value).ToString("yyyy/MM/dd");
                            param.Add(new SqlParameter("@" + item.Name, date));
                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                        }
                        else
                        {
                            param.Add(new SqlParameter("@" + item.Name, value));
                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                        }
                    }
                    else
                    {
                        if (!attribute.NotSelect)
                        {
                            var conditionsType = attribute.ConditionsTypes;
                            var symbolAttribute = attribute.SymbolAttributes;

                            switch (symbolAttribute)
                            {
                                case SymbolAttribute.EQUAL:
                                    param.Add(new SqlParameter("@" + item.Name, value));
                                    strsql.Append(" and t." + item.Name + " = @" + item.Name);
                                    break;
                                case SymbolAttribute.CONTAILS:
                                    param.Add(new SqlParameter("@" + item.Name, "%" + value + "%"));
                                    strsql.Append(" and t." + item.Name + " like @" + item.Name);
                                    break;
                                case SymbolAttribute.STARTSWITH:
                                    param.Add(new SqlParameter("@" + item.Name, "%" + value));
                                    strsql.Append(" and t." + item.Name + " like @" + item.Name);
                                    break;
                                case SymbolAttribute.ENDSWITH:
                                    param.Add(new SqlParameter("@" + item.Name, value + "%"));
                                    strsql.Append(" and t." + item.Name + " like @" + item.Name);
                                    break;
                                case SymbolAttribute.GREATER:
                                    param.Add(new SqlParameter("@" + item.Name, value));
                                    strsql.Append(" and t." + item.Name + " > @" + item.Name);
                                    break;
                                case SymbolAttribute.LESS:
                                    param.Add(new SqlParameter("@" + item.Name, value));
                                    strsql.Append(" and t." + item.Name + " < @" + item.Name);
                                    break;
                                case SymbolAttribute.GREATEREQUAL:
                                    param.Add(new SqlParameter("@" + item.Name, value));
                                    strsql.Append(" and t." + item.Name + " >= @" + item.Name);
                                    break;
                                case SymbolAttribute.LESSEQUAL:
                                    param.Add(new SqlParameter("@" + item.Name, value));
                                    strsql.Append(" and t." + item.Name + " <= @" + item.Name);
                                    break;
                                case SymbolAttribute.INTERVAL:
                                    if (attribute.IsSplit)
                                    {
                                        string[] timestring = valueS.Split(attribute.SplitString);
                                        if (timestring != null)
                                        {
                                            if (timestring.Length == 1)
                                            {
                                                param.Add(new SqlParameter("@" + item.Name + "start", timestring[0]));
                                                strsql.Append(" and (t." + item.Name + " >= @" + item.Name + "start )");
                                            }
                                            else if (timestring.Length == 2)
                                            {
                                                if (timestring[0] != "" && timestring[1] != "")
                                                {
                                                    param.Add(new SqlParameter("@" + item.Name + "start", timestring[0]));
                                                    param.Add(new SqlParameter("@" + item.Name + "end", timestring[1]));
                                                    strsql.Append(" and (t." + item.Name + " >= @" + item.Name + "start and t." + item.Name + " <= @" + item.Name + "end)");
                                                }
                                                else if (timestring[0] != "" && timestring[1] == "")
                                                {
                                                    param.Add(new SqlParameter("@" + item.Name + "start", timestring[0]));
                                                    strsql.Append(" and (t." + item.Name + " >= @" + item.Name + "start )");
                                                }
                                                else if (timestring[0] == "" && timestring[1] != "")
                                                {
                                                    param.Add(new SqlParameter("@" + item.Name + "start", timestring[1]));
                                                    strsql.Append(" and ( t." + item.Name + " <= @" + item.Name + "end)");
                                                }
                                            }
                                        }
                                    }
                                    break;
                                default:
                                    switch (conditionsType)
                                    {
                                        case ConditionsType.INT:
                                            param.Add(new SqlParameter("@" + item.Name, value));
                                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                                            break;
                                        case ConditionsType.STRING:
                                            param.Add(new SqlParameter("@" + item.Name, "%" + value + "%"));
                                            strsql.Append(" and t." + item.Name + " like @" + item.Name);
                                            break;
                                        case ConditionsType.DATETIME:
                                            var date = ((DateTime)value).ToString("yyyy/MM/dd");
                                            param.Add(new SqlParameter("@" + item.Name, date));
                                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                                            break;
                                        default:
                                            param.Add(new SqlParameter("@" + item.Name, value));
                                            strsql.Append(" and t." + item.Name + " = @" + item.Name);
                                            break;
                                    }
                                    break;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
            }
            queryParameter.Count = (await _db.Ado.SqlQueryAsync<T>(strsql.ToString(), param.ToArray())).Count();
            if (queryParameter.sidx == "")
            {
                queryParameter.sidx = "F_Id";
                queryParameter.sord = "desc";
            }
            strsql.Append($@" order by {queryParameter.sidx} {queryParameter.sord} offset {(queryParameter.pageNum - 1) * queryParameter.pageSize} rows fetch next {queryParameter.pageSize} rows only");
            return await _db.Ado.SqlQueryAsync<T>(strsql.ToString(), param.ToArray());
        }
        #endregion

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public int Count(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Count(whereExpression);
        }

        /// <summary>
        /// 获取总数
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<int> CountAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.CountAsync(whereExpression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public bool Any(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Any(whereExpression);
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.AnyAsync(whereExpression);
        }

        /// <summary>
        /// 通过主键获取实体
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public TEntity Single(dynamic Id)
        {
            return Entities.InSingle(Id);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity Single(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Single(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.SingleAsync(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.First(whereExpression);
        }

        /// <summary>
        /// 获取一个实体
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Entities.FirstAsync(whereExpression);
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public List<TEntity> ToList()
        {
            return Entities.ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public List<TEntity> ToList(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToList();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync()
        {
            return Entities.ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Entities.Where(whereExpression).ToListAsync();
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        public Task<List<TEntity>> ToListAsync(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return Entities.OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToListAsync();
        }

        /// <summary>
        /// 新增一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Insert(TEntity entity)
        {
            return _db.Insertable(entity).ExecuteCommand();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Insert(params TEntity[] entities)
        {
            return _db.Insertable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Insert(IEnumerable<TEntity> entities)
        {
            return _db.Insertable(entities.ToArray()).ExecuteCommand();
        }

        /// <summary>
        /// 新增一条记录返回自增Id
        /// </summary>
        /// <param name="insertObj"></param>
        /// <returns></returns>
        public int InsertReturnIdentity(TEntity insertObj)
        {
            return _db.Insertable(insertObj).ExecuteReturnIdentity();
        }

        /// <summary>
        /// 新增一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(TEntity entity)
        {
            return _db.Insertable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(params TEntity[] entities)
        {
            return _db.Insertable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 新增多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> InsertAsync(IEnumerable<TEntity> entities)
        {
            if (entities != null && entities.Any())
            {
                return _db.Insertable(entities.ToArray()).ExecuteCommandAsync();
            }
            return Task.FromResult(0);
        }

        /// <summary>
        /// 新增一条记录返回自增Id
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<long> InsertReturnIdentityAsync(TEntity entity)
        {
            return await _db.Insertable(entity).ExecuteReturnBigIdentityAsync();
        }

        /// <summary>
        /// 更新一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Update(TEntity entity)
        {
            return _db.Updateable(entity).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Update(params TEntity[] entities)
        {
            return _db.Updateable(entities).ExecuteCommand();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual int Update(IEnumerable<TEntity> entities)
        {
            return _db.Updateable(entities.ToArray()).ExecuteCommand();
        }

        /// <summary>
        /// 更新一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(TEntity entity)
        {
            return _db.Updateable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(params TEntity[] entities)
        {
            return _db.Updateable(entities).ExecuteCommandAsync();
        }

        /// <summary>
        /// 更新多条记录
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        public virtual Task<int> UpdateAsync(IEnumerable<TEntity> entities)
        {
            return _db.Updateable(entities.ToArray()).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int Delete(TEntity entity)
        {
            return _db.Deleteable(entity).ExecuteCommand();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual int Delete(object key)
        {
            return _db.Deleteable<TEntity>().In(key).ExecuteCommand();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual int Delete(params object[] keys)
        {
            return _db.Deleteable<TEntity>().In(keys).ExecuteCommand();
        }

        /// <summary>
        /// 自定义条件删除记录
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public int Delete(Expression<Func<TEntity, bool>> whereExpression)
        {
            return _db.Deleteable<TEntity>().Where(whereExpression).ExecuteCommand();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(TEntity entity)
        {
            return _db.Deleteable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除一条记录
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(object key)
        {
            return _db.Deleteable<TEntity>().In(key).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除多条记录
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        public virtual Task<int> DeleteAsync(params object[] keys)
        {
            return _db.Deleteable<TEntity>().In(keys).ExecuteCommandAsync();
        }

        /// <summary>
        /// 自定义条件删除记录
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await _db.Deleteable<TEntity>().Where(whereExpression).ExecuteCommandAsync();
        }

        /// <summary>
        /// 根据表达式查询多条记录
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate);
        }

        /// <summary>
        /// 根据表达式查询多条记录
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> Where(bool condition, Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable().WhereIF(condition, predicate);
        }

        /// <summary>
        /// 构建查询分析器
        /// </summary>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> AsQueryable()
        {
            return Entities;
        }

        /// <summary>
        /// 构建查询分析器
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual ISugarQueryable<TEntity> AsQueryable(Expression<Func<TEntity, bool>> predicate)
        {
            return Entities.Where(predicate);
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <returns></returns>
        public virtual List<TEntity> AsEnumerable()
        {
            return AsQueryable().ToList();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual List<TEntity> AsEnumerable(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate).ToList();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <returns></returns>
        public virtual Task<List<TEntity>> AsAsyncEnumerable()
        {
            return AsQueryable().ToListAsync();
        }

        /// <summary>
        /// 直接返回数据库结果
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual Task<List<TEntity>> AsAsyncEnumerable(Expression<Func<TEntity, bool>> predicate)
        {
            return AsQueryable(predicate).ToListAsync();
        }

        /// <summary>
        /// 切换仓储
        /// </summary>
        /// <typeparam name="TChangeEntity">实体类型</typeparam>
        /// <returns>仓储</returns>
        public virtual ISqlSugarRepository<TChangeEntity> Change<TChangeEntity>()
            where TChangeEntity : class, new()
        {
            return _sqlSugarRepository.Change<TChangeEntity>();
        }
    }
}